package de.riceman.simpleGo.view.views.visualizationView;
import java.util.AbstractSet;
import java.util.HashSet;
import java.util.Iterator;

import de.riceman.simpleGo.main.BitMatrix;


public class ForceDirectedGraph implements Graph<ForcedNode, SpringEdge> {


	private AbstractSet<ForcedNode> nodes;
	private AbstractSet<SpringEdge> edges;
	private Timer timer = new Timer();
	private double mass;
	private double stiffness;
	private double naturalLength;
	private double diameter;
	private BitMatrix adjacencies;

	public ForceDirectedGraph(BitMatrix adjacencies, double mass, double stiffness, double naturalLength, double diameter) {
		
		this.adjacencies = adjacencies;
		this.mass = mass;
		this.stiffness = stiffness;
		this.naturalLength = naturalLength;
		this.diameter = diameter;
		
		nodes = new HashSet<ForcedNode>();
		edges = new HashSet<SpringEdge>(); 
		
		//this.initialize();
		//System.out.println(this);
		
	}
	
	public void initialize() {
		
		timer.start();
		
		int i, j;
		ForcedNode n, n1, n2;
		Iterator<ForcedNode> it;
		
		for (i = 0; i < adjacencies.getColumns(); i++) {
			nodes.add(new ForcedNode(i, mass, diameter, new Vector3D(500/4 + (Math.random()*100), 500/4 + (Math.random()*100), 0)));
		}
		System.out.println("Nodes added.");
		for (i = 0; i < adjacencies.getRows(); i++) {
			for (j = i+1; j < adjacencies.getColumns(); j++) {
				if (adjacencies.get(i, j)) {
					n1 = null;
					n2 = null;
					it = nodes.iterator();
					
					while (it.hasNext()) {
						n = it.next();
						if (n.getId() == i) {
							n1 = n;
						}
						if (n.getId() == j) {
							n2 = n;
						}
					}
					System.out.println(Integer.toString(n1.getId()) + "-" + Integer.toString(n2.getId()));
					edges.add(new SpringEdge(n1, n2, stiffness, naturalLength));
					//System.out.println("new edge: " + n1.getName() + ", " + n2.getName());
				}
			}	
		}
		timer.stop();
		System.out.println("Initialization finished in " + timer.getElapsed() + " ms.");
		timer.reset();
	}
	
	public Vector3D getCentroid() {
		double x = 0.0;
		double y = 0.0;
  
		Iterator<ForcedNode> it = nodes.iterator();
  
		while (it.hasNext()) {
  
			Node n = it.next();
			x += n.getPosition().getX();
			y += n.getPosition().getY();
		}
  
		return new Vector3D(x/nodes.size(), y/nodes.size(), 0);
	}

	
	public AbstractSet<ForcedNode> getNodes() {
		
		return nodes;
	}

	
	public AbstractSet<SpringEdge> getEdges() {
	
		return edges;
	}

	public String toString() {
		
		String string = new String();
		
		Iterator<ForcedNode> it = nodes.iterator();
		  
		while (it.hasNext()) {
  
			ForcedNode node = it.next();
			
			string += "Node " + Integer.toString(node.getId());
			string += " x=" + Double.toString(node.getPosition().getX());
			string += " y=" + Double.toString(node.getPosition().getY()) + "\n";
		}
		
		Iterator<SpringEdge> edgeIt = edges.iterator();
		
		while (edgeIt.hasNext()) {
			
			SpringEdge edge = edgeIt.next();
			
			string += "Edge ";
			string += " a=" + Integer.toString(edge.getVertexA().getId());
			string += " b=" + Integer.toString(edge.getVertexB().getId()) + "\n";
			
		}
		
		return string;
	}
	
	public void setMass(double mass) {
		
		this.mass = mass;
	}

	
	public void setStiffness(double stiffness) {
	
		this.stiffness = stiffness;
	}

	
	public void setNaturalLength(double naturalLength) {
	
		this.naturalLength = naturalLength;
	}
}
